package db;

import java.util.*;

import org.hibernate.*;
import org.hibernate.cfg.Configuration;


@SuppressWarnings("unchecked")
public class DbUtils {
	private static SessionFactory mSessionFactory = null;
	
	public static Session startSession() {

		// Create the session factory (on demand)
		if (mSessionFactory == null) {
			// Load the settings from hibernate.cfg.xml
			Configuration cfg = new Configuration();
			cfg.configure();
			
			// Create Hibernate SessionFactory
			mSessionFactory = cfg.buildSessionFactory();
		}

		// Start new Hibernate session
		Session session = mSessionFactory.openSession();
		
		// Start new transaction (this is always required)
		session.beginTransaction();
		return session;
	}
	
	//add methods
	public static long addPicture(Session session, String title, String format, long albumId,Date date){
		Album album = (Album) session.get(Album.class, albumId);
		Picture pict = new Picture(title, format, date, album);
		session.save(pict);
		session.flush();
		session.evict(pict);
		return pict.getPictureId();
	}
	
	public static void addUser(Session session, String userName, String userPassword){
		User user = new User();
		user.setUserName(userName);
		user.setUserPassword(userPassword);
		session.save(user);
		session.flush();
		session.evict(user);
	}
	
	public static void addAlbum(Session session, String albumName, Long parentId){
		Album newAlbum = new Album();
		newAlbum.setAlbumName(albumName);
		Album parentAlbum = findAlbum(session, parentId);
		newAlbum.setParentAlbum(parentAlbum);
		User user = (User) parentAlbum.getUser();
		newAlbum.setUser(user);
		session.save(newAlbum);
		session.flush();
		session.evict(newAlbum);
	}
	
	public static void addAlbum(Session session, Long userId, String albumName){
		long id = getALbumIdByName(session, albumName, userId);
		if (id == -1) {
		Album newAlbum = new Album();
		newAlbum.setAlbumName(albumName);
		User user = (User) session.get(User.class, userId);
		newAlbum.setUser(user);
		session.save(newAlbum);
		session.flush();
		session.evict(newAlbum);
		}
	}
	
	public static void addComment(Session session, String content, long userId, long pictureId, Date date) {
		Comment newComment = new Comment();
		newComment.setCommentContent(content);
		newComment.setCommentDate(date);
		User user = (User)session.get(User.class, userId);
		newComment.setUser(user);
		Picture picture = (Picture) session.get(Picture.class, pictureId);
		newComment.setPicture(picture);
		session.save(newComment);
		session.flush();
		session.evict(newComment);
	}
	
	//delete methods
	public static void deleteAlbum(Session session, long id) {
		Album album = (Album) session.get(Album.class, id);
		if (album != null) {
	
			List<Picture> pics = album.getPictures();
			if(!pics.isEmpty()) {
				for(Picture pic : pics) {
					deletePicture(session, pic.getPictureId());
				}
			}
			List<Album> childs = album.getChildAlbums();
			if(!childs.isEmpty()) {
				for(Album child : childs) {
					deleteAlbum(session, child.getAlbumId());
				}
			}
			session.update(album);
			session.delete(album);
		}
	}
	
	public static void deletePicture(Session session, long id) {
		Picture pict = (Picture) session.get(Picture.class, id);
		List<Comment> comments = pict.getComments();
		if(!comments.isEmpty()) {
			for(Comment comment : comments) {
				session.delete(comment);
			}
			session.flush();
		}
		session.delete(pict);
	}
	
	public static void deleteUser(Session session, long id) {
		User user = (User) session.get(User.class, id);
		List<Album> albums = getAllAlbumsByUser(session, id);
		if(!albums.isEmpty()) {
			for(Album album : albums) {
				deleteAlbum(session, album.getAlbumId());
			}
		}
		session.flush();
		session.delete(user);
	}
	
	public static void deleteComment(Session session, long commentId) {
		Comment comment = (Comment) session.get(Comment.class, commentId);
		session.flush();
		session.delete(comment);
	}
	
	//get methods
	public static List<User> getAllUsers(Session session) {
		Query allUsersQuery = session.createQuery("from User");
		return allUsersQuery.list();
	}
	
	public static List<Picture> get16Pictures(Session session, int pageNumber) {
		Query picturesQuery = session.createQuery("from Picture order by PictureDate desc");
		int page = pageNumber -1;
		picturesQuery.setFirstResult(page * 16);
		picturesQuery.setMaxResults(16);
		return picturesQuery.list();
	}
	
	
	public static List<Picture> get16Pictures(Session session, int pageNumber, long albumId) {
		Query picturesQuery = session.createQuery("from Picture " +
				"where Album.AlbumId = :id order by PictureDate desc");
		picturesQuery.setLong("id", albumId);
		int page = pageNumber -1;
		picturesQuery.setFirstResult(page * 16);
		picturesQuery.setMaxResults(16);
		return picturesQuery.list();
	}
	
	public static List<Comment> getCommentsByPicture(Session session, long pictId) {
		Query commentQuery = session.createQuery("from Comment where Picture.PictureId = :id order by CommentDate desc");
		commentQuery.setLong("id", pictId);
		return commentQuery.list();
	}
	
	public static Comment getCommentbyId(Session session, long commId) {
		Query commentQuery = session.createQuery("from Comment where CommentId = :id");
		commentQuery.setLong("id", commId);
		 List<Comment> comments= commentQuery.list();
		 if(comments.size() < 1) {
				return null;
			}
			Comment comment = comments.get(0);
			return comment;
	}
	
	public static String getPicturePath(Session session, long id) {
		Picture pict = (Picture) session.get(Picture.class, id);
		String path =pict.getAlbum().getAlbumName() + " / " + pict.getPictureTitle() + "." + pict.getPictureFormat();
		Album parentAlbum = pict.getAlbum().getParentAlbum();
		while(parentAlbum != null) {
			path = parentAlbum.getAlbumName() + " / " + path;
			parentAlbum = parentAlbum.getParentAlbum();
		}
		return path;
	}
	
	public static Picture getPicturebyId(Session session, long imageId) {
		Picture pict = (Picture) session.get(Picture.class, imageId);
		return pict;
	}
	
	public static String getAlbumPath(Session session, long id) {
		Album album = (Album) session.get(Album.class, id);
		String path = album.getAlbumName();
		Album parentAlbum = album.getParentAlbum();
		while(parentAlbum != null) {
			path = parentAlbum.getAlbumName() + "/" + path;
			parentAlbum = parentAlbum.getParentAlbum();
		}
		return path;
	}
	
	public static long getAllPicturesNum(Session session) {
		Query picturesQuery = session.createQuery("from Picture");
		List<Picture> pics = picturesQuery.list();
		return pics.size();
	}
	
	public static long getAllPicturesNumByAlbum(Session session, long albumId) {
		Query allPicsByAlbum = session.createQuery("from Picture where AlbumId = :id");
		allPicsByAlbum.setLong("id", albumId);
		List<Picture> allPics = allPicsByAlbum.list();
		return allPics.size();
	}
	
	public static List<Picture> getAllPicturesByAlbum(Session session, long albumId) {
		Query allPicsByAlbum = session.createQuery("from Picture where AlbumId = :id");
		allPicsByAlbum.setLong("id", albumId);
		return allPicsByAlbum.list();
	}
	
	public static List<Album> getUserAlbums(Session session, long userId) {
//		User user = (User) session.get(User.class, userId);
		Query allAlbumsQuery = session.createQuery("from Album where User.UserId = :userId order by AlbumId");
		allAlbumsQuery.setLong("userId", userId);
		List<Album> userAlbums = allAlbumsQuery.list();
		return userAlbums;
	}
	
	public static Album getAlbumbyId(Session session, long albumId) {
		Query alQuery = session.createQuery("from Album where AlbumId = :id");
		alQuery.setLong("id", albumId);
		 List<Album> albums= alQuery.list();
		 if(albums.size() < 1) {
				return null;
			}
			Album al = albums.get(0);
			return al;
	}
	
	public static Long getUserIdByUserName(Session session, String userName) {
		Query query = session.createQuery("from db.User where UserName = :userName");
		query.setString("userName", userName);
		List<User> users = query.list();
		if(users.size() < 1) {
			return null;
		}
		User user = users.get(0);
		long userId = user.getUserId();
		return userId;
	}

	public static List<Album> getAllAlbums(Session session) {
		Query allAlbumsQuery = session.createQuery("from Album where ParentAlbum.AlbumId is null");
		return allAlbumsQuery.list();
	}
	
	public static List<Album> get16ChildAlbumsByParent(Session session, long parentId, int pageNumber) {
		Query allChildAlbumsQuery = session.createQuery("from Album where ParentAlbum.AlbumId= :id");
		allChildAlbumsQuery.setLong("id", parentId); 
		int page = pageNumber -1;
		allChildAlbumsQuery.setFirstResult(page * 16);
		allChildAlbumsQuery.setMaxResults(16);
		return allChildAlbumsQuery.list();
	}
	
	public static List<Album> getAllExistAlbums(Session session) {
		Query allAlbumsQuery = session.createQuery("from Album order by AlbumId");
		return allAlbumsQuery.list();
	}
	
	
	public static List<Album> get16Albums(Session session, int pageNumber) {
		Query picturesQuery = session.createQuery("from Album where ParentAlbum.AlbumId is null");
		int page = pageNumber -1;
		picturesQuery.setFirstResult(page * 16);
		picturesQuery.setMaxResults(16);
		return picturesQuery.list();
	}
	
	public static long getALbumIdByName(Session session, String albumName, long userId) {
		Query getAlbumQuery = session.createQuery("from Album where AlbumName like :name and User.UserId = :id");
		getAlbumQuery.setString("name", albumName);
		getAlbumQuery.setLong("id", userId);
		List<Album> ids = getAlbumQuery.list();
		long id = -1;
		if (ids.size() != 0)
		id = ids.get(0).getAlbumId();
		return id;
	}
	
	public static List<Album> getAllAlbumsByUser(Session session, long userId) {
		Query getAlbumQuery = session.createQuery("from Album where User.UserId = :id");
		getAlbumQuery.setLong("id", userId); 
		return getAlbumQuery.list();
	}
	
	//edit methods
	public static void editComment(Session session, long commentId, String newContent) {
		Comment comment = (Comment) session.get(Comment.class, commentId);
		comment.setCommentContent(newContent);
		session.update(comment);
	}
	
	public static void editPicture(Session session, long imageId, String newTitle, long albumId) {
		Picture picture = (Picture) session.get(Picture.class, imageId);
		picture.setPictureTitle(newTitle);
		Album album = (Album) session.get(Album.class, albumId);
		picture.setAlbum(album);
		session.update(picture);
	}
	
	public static void editAlbum(Session session,  String newTitle, long albumId) {
		Album album = (Album) session.get(Album.class, albumId);
		album.setAlbumName(newTitle);
		session.update(album);
	}
	
	public static void editUserName(Session session, String userName, long id) {
		User user = (User) session.get(User.class, id);
		user.setUserName(userName);
		session.update(user);
	}
	
	public static void editUserPassword(Session session, String password, long id) {
		User user = (User) session.get(User.class, id);
		user.setUserPassword(password);
		session.update(user);
	}
	
	//boolean methods
	public static boolean isValidUser(Session session, String userName, String userPassword) {
		Query userQuery = session.createQuery("from db.User where UserName = :user and UserPassword = :pass");
		userQuery.setParameter("user", userName);
		userQuery.setParameter("pass", userPassword);
		List<User> users = (List<User>) userQuery.list();
		if(users.size() == 1) {
			return true;
		} else {
			return false;
		}
	}
	
	public static boolean isUserPicture(Session session, long userId, long pictureId) {
		Picture pict = (Picture) session.get(Picture.class, pictureId);
		if(pict.getAlbum().getUser().getUserId() == userId) {
			return true;
		}else {
			return false;
		}
	}
	
	public static boolean isUserPicture(Session session, String userName, long pictureId) {
		Picture picture = (Picture) session.get(Picture.class, pictureId);
		String userOwningThePicture = picture.getAlbum().getUser().getUserName();
		if(userOwningThePicture.equals(userName)) {
			return true;
		} else {
			return false;
		}
	}
	
	public static boolean isUserAlbum(Session session, long userId, long albumId) {
		Album album = (Album) session.get(Album.class, albumId);
		if(album.getUser().getUserId() == userId) {
			return true;
		}else {
			return false;
		}
	}
	
	
	public static boolean isUserComment(Session session, long userId, long commentId) {
		Comment comment = (Comment) session.get(Comment.class, commentId);
		if(comment.getUser().getUserId() == userId) {
			return true;
		}else {
			return false;
		}
	}
	
	//find methods
	public static Album findAlbum(Session session, long id) {
		Album album = (Album) session.get(Album.class, id);
		return album;
	}
	
	public static List<Picture> findPicture(Session session, String name) {
		Query findPictureQuery = session.createQuery("from Picture where upper(PictureTitle) like upper(:name) order by PictureDate desc");
		name = name.replace("\\", "\\\\");
		name = name.replace("%", "\\%");
		name = name.replace("_", "\\_");
		findPictureQuery.setString("name", '%' + name + '%');
		List<Picture> findedPictures = findPictureQuery.list();		
		return findedPictures;
	}
}
